package com.chinacache.maint.workorder.service;

import java.util.List;

import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Required;
import org.springframework.transaction.annotation.Transactional;

import com.chinacache.maint.commons.entity.BaseEntity;
import com.chinacache.maint.commons.orm.hibernate.Page;
import com.chinacache.maint.commons.orm.hibernate.SimpleHibernateDao;
import com.chinacache.maint.workorder.entity.Flow;

@Transactional
public class FlowManager {
	private SimpleHibernateDao<Flow, Integer> flowDao;

	@Required
	public void setSessionFactory(SessionFactory sessionFactory) {
		flowDao = new SimpleHibernateDao<Flow, Integer>(sessionFactory,
				Flow.class);
	}

	@Transactional(readOnly = true)
	public Flow getFlow(Integer id) {
		return flowDao.findById(id);
	}

	@Transactional(readOnly = true)
	public Page<Flow> getAllFlow(Page<Flow> page) {
		return flowDao.findAll(page);
	}

	@Transactional(readOnly = true)
	public Page<Flow> getAllFlowByFlowClassId(Page<Flow> page,
			Integer flowClassId) {
		String hqlString = "select flow from Flow flow where flow.flowClass.id="
				+ flowClassId + " order by flow.order";
		return flowDao.find(page, hqlString);
	}

	@Transactional(readOnly = true)
	public List<Flow> getAllFlowByFlowClassId(Integer flowClassId) {
		String hqlString = "select flow from Flow flow where flow.flowClass.id="
				+ flowClassId + " order by flow.order";
		return flowDao.find(hqlString);
	}

	@Transactional(readOnly = true)
	public Integer getFlowCountByFlowClassId(Integer flowClassId) {
		String hqlString = "select count(*) from Flow f where f.flowClass.id=?";
		return flowDao.findInt(hqlString, flowClassId);
	}

	@Transactional(readOnly = true)
	public Page<Flow> isHaveCompleteFlow(Page<Flow> page, Integer flowClassId) {
		String hqlString = "select flow from Flow flow where flow.status in ("
				+ BaseEntity.FLOW_STATUS_START + ","
				+ BaseEntity.FLOW_STATUS_END + ") and flow.flowClass.id="
				+ flowClassId;
		return flowDao.find(page, hqlString);
	}

	@Transactional(readOnly = true)
	public Flow getFlowByOrderAndFlowClassId(Integer order, Integer flowClassId) {
		String hqlString = "select flow from Flow flow where flow.order="
				+ order + " and flow.flowClass.id=" + flowClassId;
		if (flowDao.find(hqlString).size() > 0)
			return (Flow) flowDao.find(hqlString).get(0);
		else {
			return null;
		}
	}

	@Transactional(readOnly = true)
	public Flow getFlowByStatusAndFlowClassId(Integer status,
			Integer flowClassId) {
		String hqlString = "select flow from Flow flow where flow.status="
				+ status + " and flow.flowClass.id=" + flowClassId;
		if (flowDao.find(hqlString).size() > 0)
			return (Flow) flowDao.find(hqlString).get(0);
		else {
			return null;
		}
	}

	@Transactional(readOnly = true)
	public List<Flow> getFlowAboveOrderAndFlowClassId(Integer order,
			Integer flowClassId) {
		String hqlString = "select flow from Flow flow where flow.order>"
				+ order + " and flow.flowClass.id=" + flowClassId;
		if (flowDao.find(hqlString).size() > 0)
			return flowDao.find(hqlString);
		else {
			return null;
		}
	}

	public void deleteFlowByAction(Integer id, Integer flowClassId) {
		Flow flow = getFlow(id);
		if (flow.getStatus().intValue() == BaseEntity.FLOW_STATUS_END) {
			Flow updateFlow = getFlowByOrderAndFlowClassId(flow.getOrder()
					.intValue() - 1, flow.getFlowClass().getId());
			if (updateFlow.getStatus() != BaseEntity.FLOW_STATUS_START)
				updateFlow.setStatus(BaseEntity.FLOW_STATUS_END);
			updateFlow(updateFlow);
			deleteFlow(id);
		} else if (flow.getStatus().intValue() == BaseEntity.FLOW_STATUS_START) {
			Flow updateFlow = getFlowByOrderAndFlowClassId(flow.getOrder()
					.intValue() + 1, flow.getFlowClass().getId());
			if (updateFlow != null) {
				updateFlow.setStatus(BaseEntity.FLOW_STATUS_START);
				updateFlow.setOrder(flow.getOrder());
				updateFlow(updateFlow);
				deleteFlow(id);
				int order = updateFlow.getOrder();
				for (Flow f : getAllFlowByFlowClassId(flowClassId)) {
					if (f.getId().intValue() != updateFlow.getId().intValue()) {
						order++;
						f.setOrder(order);
						updateFlow(updateFlow);
					}

				}
			} else {
				deleteFlow(id);
			}

		} else {
			int order = flow.getOrder();
			List<Flow> fs = getFlowAboveOrderAndFlowClassId(flow.getOrder(),
					flowClassId);
			for (Flow f : fs) {
				f.setOrder(order);
				updateFlow(f);
				order++;

			}
			deleteFlow(id);
		}

	}

	public Flow getFlowByAudit(Integer flowClassId, Integer audit) {
		String queryString = "select flow from Flow flow where flow.audit="
				+ audit + " and flow.flowClass.id=" + flowClassId;
		if (flowDao.find(queryString).size() == 0) {
			return null;
		} else {
			return (Flow) flowDao.findUnique(queryString);
		}
	}

	public void saveFlow(Flow flow) {
		flowDao.save(flow);
	}

	public void deleteFlow(Integer id) {
		Flow flow = flowDao.findById(id);
		flowDao.delete(flow);
	}

	public void updateFlow(Flow flow) {
		flowDao.update(flow);
	}

	@Transactional(readOnly = true)
	public List<Flow> getAllFlow() {
		return flowDao.findAll();
	}
}
